#include <stdlib.h>
#include <locale.h>
#include "boost/locale/encoding.hpp"
#include "BSException/BSException.h"
#include "UTF8.h"

#define UTF8_ENCODE_STRING "UTF8"

#define GBK_ENCODE_STRING "GBK"

#define GB2312_ENCODE_STRING "GB2312"

using namespace SystemTool::Encoding;

// Get utf8 string
std::string UTF8::GetString(const std::string strData, EncodeType eEncodeType)
{
	if (strData.empty())
	{
		return "";
	}

	try
	{
		if (eEncodeType == ENCODE_GBK)
		{
			return boost::locale::conv::to_utf<char>(strData, GBK_ENCODE_STRING);
		}
		else if (eEncodeType == ENCODE_GB2312)
		{
			return boost::locale::conv::to_utf<char>(strData, GB2312_ENCODE_STRING);
		}
		else if (eEncodeType == ENCODE_UTF8)
		{
			return strData;
		}
	}
	catch (std::bad_cast & e)
	{
		throw BSException() << e.what();
	}

	return "";
}

// Get utf8 string
std::string UTF8::GetString(const std::wstring strUnicodeData, EncodeType eEncodeType)
{
	if (strUnicodeData.empty())
	{
		return "";
	}

	try
	{
		std::string strFinalData = "";

		std::wstring strWData = strUnicodeData;

		if (eEncodeType == ENCODE_GBK || eEncodeType == ENCODE_GB2312)
		{
			std::locale old_loc = std::locale::global(std::locale(""));

			int iTotalSize = wcslen(strWData.c_str()) * sizeof(wchar_t) + sizeof(int);

			char* pBuffer = new char[iTotalSize];

			if (pBuffer == NULL)
			{
				return "";
			}

			size_t iBufferSize = iTotalSize * sizeof(char);

			memset(pBuffer, 0, iBufferSize);

			wcstombs(pBuffer, strWData.c_str(), iBufferSize);

			strFinalData = pBuffer;

			if (pBuffer)
			{
				delete[] pBuffer;

				pBuffer = NULL;
			}

			std::locale::global(old_loc);

			// Gbk multi byte string to utf8 multi byte string
			return boost::locale::conv::to_utf<char>(strFinalData, GBK_ENCODE_STRING);
		}

		// Utf8 wide string to utf8 multi byte string
		return boost::locale::conv::utf_to_utf<char>(strWData);
	}
	catch (std::bad_cast & e)
	{
		throw BSException() << e.what();
	}

	return "";
}
